Spring Boot 读取与自动配置
读取
Environment
Environment是用于读取应用程序运行时环境变量的类,是可通过在application.properties中写入的key来通过Environment类读取的一种方式,而通过这种方式来读取的实现类通常称之为“Environment”类。
src/main/resources/application.properties
1
| demo.msg = Hello I am here read config!
|
HelloWorldController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
@RestController public class HelloWorldController { @Autowired private Environment env; @RequestMapping("/demoEnv") public String demoEnv() { return "Spring boot:" + env.getProperty("demo.msg"); } }
|
@Value
第二种方法就是使用@value注解来进行读取,与Environment的区别就是少了一行code,就是说用注解代替了Environment的return,来读取application.properties:
src/main/resources/application.properties
1
| demo.msg = Hello I am here read config!
|
HelloWorldController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.example.demo;
import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
@RestController public class HelloWorldController { @Value("${demo.msg}") private String msg; @RequestMapping("/demoValue") public String demoValue() { return "Spring boot" + msg; } }
|
@PropertySource
在前面所介绍的注解仅仅可用于读取application.properties的Spring boot全局配置文件,而如果想要读取另一个或其他的配置文件需要使用到@PropertySource + @Value来读取其他配置文件的内容,其步骤如下:
PropertySourceValueReaderOtherController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.example.demo; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
@RestController @PropertySource({"one.properties","two.properties"}) public class PropertySourceValueReaderOhterController { @Value("${two.msg}") private String twomsg; @Value("${one.msg}") private String onemsg; @RequestMapping("/demoProperty") public String demoProperty() { return "one.properties:" + twomsg + "<br>" + "two.properties:" + twomsg; } }
|
one.properties
two.properties
1
| two.msg = test PropertySource
|
@ConfigurationProperties
```@Value、@PropertySource```注解类似,通过使用该注解可以配置 Controller、Model 进行获取 ```application.properties``` 配置文件信息。1 2 3 4 5 6 7 8
| #### application.properties ```java com.example.name=${name:sunlikun} com.exmaple.age=16 com.example.address[0]=one com.example.address[1]=two com.example.address[2]=three
|
ConfigExampleModel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package com.example.demo.model;
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component;
import java.util.List;
@Data @Component @ConfigurationProperties(prefix = "com.example") public class ConfigExampleModel {
private String name; private int age; private List<String> address; }
|
ConfigExampleController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| package com.example.demo.controller;
import com.example.demo.model.ConfigExampleModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController public class ConfigExampleController { @Autowired private ConfigExampleModel configExampleModel;
@RequestMapping("/") public String getName() { return configExampleModel.getName(); }
@RequestMapping("/address") public List<String> getAddress() { return configExampleModel.getAddress(); } }
|
当一切完成之后我们访问 http://localhost:8080/address 会发现返回的是 ["one","two","three"],或者访问 http://localhost:8080/ 进行测试,此时返回的结果则是 sunlikun,而这正是 application.properties 下配置文件的内容数据。
日志
在众多的开发语言之中,日志是最为重要的一个功能,虽然这里说的开发语言不指java、c\c++、php这些,但是我们可拿mysql为例,在mysql中,日志是非常好的排错工具,通过阅读日志信息可帮助我们快速的了解错误和安全性的信息,学习spring boot自动配置之前,我们需要预先连接下spring boot的日志生成和管理以及对日志的配置。通常我们使用apache下的Log、LogFactory的方式来实现日志,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.example.demo;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
@RestController public class LogTestController { private Log log = LogFactory.getLog(LogTestController.class); @RequestMapping("/testLog") public String testLog() { log.info("test log"); return "test Log"; } }
|
日志等级
在Spring boot中,日志等级和一些日志配置都是在application.properties文件下进行设置的,通常存储在src/main/resources目录下,而日志等级主要分为五个等级级别,以及三个颜色等级,共分别为:
| ID |
DA |
FA |
| OFF |
关闭 |
无颜色 |
| FATAL |
致命 |
红色 |
| ERROR |
错误 |
红色 |
| WARN |
警告 |
黄色 |
| INFO |
信息 |
绿色 |
| DEBUG |
调试 |
绿色 |
| TREACE |
追踪 |
绿色 |
| ALL |
所有 |
无颜色 |
| 通常我们可以使用针对默认和设置指定包下的日志等级两种方式为: |
|
|
默认日志等级设置
1 2
| # 设置日志的默认等级为 info logging.level.root = info
|
指定包下的日志等级设置
1 2
| # 设置 com.example.demo 包下日志等级为 off 即关闭 logging.level.com.example.demo = off
|
日志目录
在spring boot全局配置文件中,默认是在启动时输出日志文件,而不会针对性的单个生成一个日志文件,这就显得单个生成日志文件存储是多么重要,通常我们可以在spring boot全局配置文件中的application.properties文件中设置:
1
| logging.file = spring.log
|
以上是针对于spring.log是存放于spring项目目录下的,如果运行后spinrg boot发现日志文件并没有写入则是可能spring boot未找到spring.log日志文件,而遇到这种事情 spring boot提供了一个完美的解决方案就是通过使用相对目录进行指定:
1
| logging.file.name=/home/kunlun/Development/Web/Demo/Spring/demo/src/main/resources/spring.log
|
在spring boot logging日志中有一个非常好的功能呢个就是,如果当日志文件超过了10mb时,将会自动生成一个新的日志文件。与此同时spring boot提供了日志的自定义,如自定义错误的颜色以及时间、等级、长度、方法名、代码行等自定义,有兴趣的读者可通过查看spring boot 关于日志这一篇的文档:https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-logging
自动配置原理
在spring boot中,@SpringBootApplication注解之中,主要调用并使用了@EnableAutoConfiguration注解来进行标注,从而实现spring boot的自动配置功能,来帮助开发者解决spirng原生的蛋疼配置问题,我们可以通过阅读spring boot的@EnableAutoCOnfiguratiot的官方Java Doc的官方文档和其依赖的源代码查看并理解其Spirng boot自动配置的原理。
EnableAutoConfiguration.class
1 2 3 4 5 6 7 8 9 10 11 12 13
|
Class<?>[] exclude() default {};
String[] excludeName() default {};
|
通常只要是一个标准的Spring boot代码都会使用 @SpringBootApplication注解,而通过阅读@SpringBootApplication对应的代码我们发现了@SpringBootApplication注解包含了@EnableAutoOnfiguration注解,而进一步阅读源代码后发现其在Springboot启动的时候会夹在主配置类AutoConfigurationImportSelector.class
AutoConfigurationImportSelector.class
1 2 3 4 5 6 7 8 9 10
| @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); }
|
1 2 3 4
| protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() { return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader); }
|
1 2 3 4 5 6 7 8 9 10 11
| protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } AnnotationAttributes attributes = getAttributes(annotationMetadata); List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); configurations = removeDuplicates(configurations);
}
|
从上述代码我们可以大概的了解到Spring Boot是通过加载所有的jar文件来实现自动配置的,所以@SpringBootApplication是通过使用@EnableAutoConfiguration注解自动配置的原理即从class目录中搜索所有的spring.factories配置文件并将其中EnableAutoConfiguration对应的配置项通过java反射机制进行实例化之后夹在到spring ioc容器中。
⬅️ Go back